package com.wsoft.system.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wsoft.constant.redis.RedisKeyConstant;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.service.RedisService;
import com.wsoft.core.vo.DictDataCacheVO;
import com.wsoft.enums.DictTypeEnum;
import com.wsoft.service.IDictCacheService;
import com.wsoft.system.dto.TsDictDataDto;
import com.wsoft.system.entity.TsDictDataEntity;
import com.wsoft.system.entity.TsDictEntity;
import com.wsoft.system.manager.DictDataManager;
import com.wsoft.system.manager.DictManager;
import com.wsoft.system.mapper.TsDictDataMapper;
import com.wsoft.system.query.dict.TsDictDataReq;
import com.wsoft.system.query.dict.TsTreeQuery;
import com.wsoft.system.service.ITsDictDataService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wsoft.system.service.ITsDictService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据字典明细表 服务实现类
 * </p>
 *
 * @author kyle
 * @since 2024年08月29日 14:38:25
 */
@Service
public class TsDictDataServiceImpl extends ServiceImpl<TsDictDataMapper, TsDictDataEntity> implements ITsDictDataService {

    @Resource
    private DictDataManager dictDataManager;
    @Resource
    private ITsDictService dictService;
    @Resource
    private RedisService redisService;
    @Resource
    private IDictCacheService dictCacheService;
    @Resource
    private DictManager dictManager;



    @Override
    public boolean insert(TsDictDataReq req) {
        TsDictDataEntity entity = Convert.convert(TsDictDataEntity.class, req);
        TsDictEntity dict = dictService.getById(req.getDictId());
            QueryWrapper<TsDictDataEntity> query = new QueryWrapper<>();
            query.lambda().eq(TsDictDataEntity::getDictId,req.getDictId())
                    .eq(TsDictDataEntity::getDictId,entity.getDictId())
                    .eq(TsDictDataEntity::getCode,entity.getCode());
            List<TsDictDataEntity> list = list(query);
        if (list.size()>0){
            Asserts.fail("[sys.code.exist]");
        }
        if (entity.getPid()==null){
            entity.setPid(0L);
        }
        boolean b = save(entity);
        if (b){
            //清空redis
            redisService.del(RedisKeyConstant.DICT_CACHE_ALL);
            redisService.del(RedisKeyConstant.DICT_CACHE_ALL_NO_TREE);
            redisService.del(RedisKeyConstant.DICT_CACHE+dict.getCode());
        }
        return b;
    }

    @Override
    public boolean update(TsDictDataReq req) {
        TsDictDataEntity entity = Convert.convert(TsDictDataEntity.class, req);
        TsDictEntity dict = dictService.getById(req.getDictId());
        QueryWrapper<TsDictDataEntity> query = new QueryWrapper<>();
        query.lambda().eq(TsDictDataEntity::getCode,entity.getCode())
                .eq(TsDictDataEntity::getDictId,entity.getDictId())
                .ne(TsDictDataEntity::getId,entity.getId());
        List<TsDictDataEntity> list = list(query);
        if (list.size()>0){
            Asserts.fail("[sys.code.exist]");
        }
        boolean b = updateById(entity);
        if (b){
            //清空redis
            redisService.del(RedisKeyConstant.DICT_CACHE_ALL);
            redisService.del(RedisKeyConstant.DICT_CACHE_ALL_NO_TREE);
            redisService.del(RedisKeyConstant.DICT_CACHE+dict.getCode());
        }
        return b;
    }

    @Override
    public boolean delete(Long id) {
        TsDictDataEntity dictData = getDictData(id);
        TsDictEntity dict = dictService.getDict(dictData.getDictId());
        QueryWrapper<TsDictDataEntity> query = new QueryWrapper<>();
        query.lambda().eq(TsDictDataEntity::getPid,id);
        if (count(query)>0){
            Asserts.fail("[dict.childData.exist]");
        }
        boolean b = removeById(id);
        if (b){
            //清空redis
            redisService.del(RedisKeyConstant.DICT_CACHE_ALL);
            redisService.del(RedisKeyConstant.DICT_CACHE_ALL_NO_TREE);
            redisService.del(RedisKeyConstant.DICT_CACHE+dict.getCode());
        }
        return b;
    }

    @Override
    public TsDictDataEntity getDictData(Long id) {
        return getById(id);
    }

    @Override
    public List<TsDictDataDto> getDictDataList(Long id) {
        TsDictEntity dict = dictService.getDict(id);
        Object cacheValue = redisService.get(RedisKeyConstant.DICT_CACHE + dict.getCode());
        if (cacheValue instanceof List) {
            return JSONArray.parseArray(JSONObject.toJSONString(cacheValue), TsDictDataDto.class);
        }
        else {
            //无缓存 查询数据库
            List<TsDictDataEntity> data = dictDataManager.getDataByDictId(dict.getId());
            List<TsDictDataDto> collect = data.stream().map(e -> Convert.convert(TsDictDataDto.class, e)).collect(Collectors.toList());
            if (data.size() <= 0) {
                return new ArrayList<>();
            }
            //树形字典
            List<TsDictDataDto> result = new ArrayList<>();
            if (dict.getDictType() == DictTypeEnum.TREE.getCode()) {
                result = toTree(data, 0L);
                    redisService.set(RedisKeyConstant.DICT_CACHE + dict.getCode(),result);
            }
            //常规字典
            if (dict.getDictType() == DictTypeEnum.NORMAL.getCode()) {
                    redisService.set(RedisKeyConstant.DICT_CACHE + dict.getCode(),collect);
                result =collect;
                }
            return result;
        }
    }

    @Override
    public List<DictDataCacheVO> getTreeData(TsTreeQuery treeQuery) {
        List<TsDictEntity> list = dictManager.getDictByCode(treeQuery.getDictCode());
        Long dictId =list.get(0).getId();
        if (treeQuery.isLazyLoad()){
            List<TsDictDataEntity> dataList = new ArrayList<>();
            if (StrUtil.isNotBlank(treeQuery.getDataCode())){
                List<TsDictDataEntity> data = dictDataManager.getDataByCode(dictId, treeQuery.getDataCode(), null);
                Long dictDataId = data.get(0).getId();
                dataList = dictDataManager.getDataByCode(dictId, null, dictDataId);
            }
            else {
                dataList =  dictDataManager.getDataByCode(dictId, null,0L);
            }
            List<DictDataCacheVO> collect = dataList.stream().map(e -> Convert.convert(DictDataCacheVO.class, e)).collect(Collectors.toList());
            collect.forEach(e -> {
                List<TsDictDataEntity> count = dictDataManager.getDataByCode(dictId, null, e.getId());
                if (count.size()>0){
                    e.setHasChild(true);
                }
                else {
                    e.setHasChild(false);
                }
            });
            return collect;
        }
        return dictCacheService.getDictByCode(treeQuery.getDictCode());
    }


    private List<TsDictDataDto> toTree(List<TsDictDataEntity> list, Long parentId) {
        // 扁平数据
        List<TsDictDataDto> lineList = new ArrayList<>();
        for (TsDictDataEntity e : list) {
            TsDictDataDto dto = Convert.convert(TsDictDataDto.class, e);
            lineList.add(dto);
        }
        Map<String, TsDictDataDto> temp = new LinkedHashMap<>();
        Map<String, TsDictDataDto> tree = new LinkedHashMap<>();
        for (TsDictDataDto g : lineList) {
            temp.put(g.getId().toString(), g);
        }
        for (String key : temp.keySet()) {
            TsDictDataDto dictData = temp.get(key);

            if ( dictData.getPid().equals(parentId)) {
                tree.put(dictData.getId().toString(), dictData);
            } else {
                if (temp.get(dictData.getPid().toString()) == null) {
                    continue;
                }
                if (temp.get(dictData.getPid().toString()).getChildren() == null) {
                    temp.get(dictData.getPid().toString()).setChildren(new ArrayList<>());
                }
                temp.get(dictData.getPid().toString()).getChildren().add(dictData);
            }
        }
        // 树状数据
        List<TsDictDataDto> treeList = new ArrayList<>();
        for (String key : tree.keySet()) {
            treeList.add(tree.get(key));
        }
        return treeList;
    }
}
